package com.cencat.merchant.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cencat.merchant.entity.RouteInvoice;
import com.cencat.merchant.mapper.RouteInvoiceMapper;
import com.cencat.merchant.service.RouteInvoiceService;
import com.cencat.merchant.vo.RouteInvoiceVO;
import com.cencat.merchant.dto.RouteInvoiceDTO;
import com.cencat.merchant.dto.RouteInvoiceQueryDTO;
import com.cencat.merchant.dto.RouteInvoiceBatchUpdateDTO;
import com.cencat.merchant.dto.RouteInvoiceStatisticsDTO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 路线发票管理服务实现类
 * 提供路线发票的增删改查、统计分析、税务分析、合规性检查等功能的具体实现
 * 
 * @author cencat
 * @version 1.0
 * @since 2025-01-20
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class RouteInvoiceServiceImpl implements RouteInvoiceService {

    @Autowired
    private RouteInvoiceMapper routeInvoiceMapper;

    @Override
    public Page<RouteInvoiceVO> getRouteInvoiceList(Page<RouteInvoice> page, RouteInvoiceQueryDTO queryDTO) {
        Page<RouteInvoice> routeInvoicePage = routeInvoiceMapper.selectRouteInvoicePage(page, queryDTO);
        Page<RouteInvoiceVO> voPage = new Page<>(routeInvoicePage.getCurrent(), routeInvoicePage.getSize(), routeInvoicePage.getTotal());
        
        List<RouteInvoiceVO> voList = routeInvoicePage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        voPage.setRecords(voList);
        
        return voPage;
    }

    @Override
    public RouteInvoiceVO getRouteInvoiceById(Long id) {
        RouteInvoice routeInvoice = routeInvoiceMapper.selectById(id);
        return routeInvoice != null ? convertToVO(routeInvoice) : null;
    }

    @Override
    public Boolean createRouteInvoice(RouteInvoiceDTO routeInvoiceDTO) {
        // 检查发票号码是否已存在
        if (existsByInvoiceNo(routeInvoiceDTO.getInvoiceNo(), null)) {
            throw new RuntimeException("发票号码已存在: " + routeInvoiceDTO.getInvoiceNo());
        }
        
        RouteInvoice routeInvoice = convertToEntity(routeInvoiceDTO);
        routeInvoice.setCreateTime(LocalDateTime.now());
        routeInvoice.setUpdateTime(LocalDateTime.now());
        
        return routeInvoiceMapper.insert(routeInvoice) > 0;
    }

    @Override
    public Boolean updateRouteInvoice(Long id, RouteInvoiceDTO routeInvoiceDTO) {
        RouteInvoice existingRouteInvoice = routeInvoiceMapper.selectById(id);
        if (existingRouteInvoice == null) {
            throw new RuntimeException("路线发票不存在: " + id);
        }
        
        // 检查发票号码是否已存在（排除当前记录）
        if (existsByInvoiceNo(routeInvoiceDTO.getInvoiceNo(), id)) {
            throw new RuntimeException("发票号码已存在: " + routeInvoiceDTO.getInvoiceNo());
        }
        
        RouteInvoice routeInvoice = convertToEntity(routeInvoiceDTO);
        routeInvoice.setId(id);
        routeInvoice.setUpdateTime(LocalDateTime.now());
        
        return routeInvoiceMapper.updateById(routeInvoice) > 0;
    }

    @Override
    public Boolean deleteRouteInvoice(Long id) {
        RouteInvoice routeInvoice = routeInvoiceMapper.selectById(id);
        if (routeInvoice == null) {
            throw new RuntimeException("路线发票不存在: " + id);
        }
        
        return routeInvoiceMapper.deleteById(id) > 0;
    }

    @Override
    public Boolean batchDeleteRouteInvoices(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        
        return routeInvoiceMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public Boolean batchUpdateInvoiceType(List<Long> ids, String invoiceType) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        
        return routeInvoiceMapper.batchUpdateInvoiceType(ids, invoiceType) > 0;
    }

    @Override
    public Boolean batchUpdateTaxRate(List<Long> ids, BigDecimal taxRate) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        
        return routeInvoiceMapper.batchUpdateTaxRate(ids, taxRate) > 0;
    }

    @Override
    public Boolean batchUpdateInvoiceAmount(List<Long> ids, BigDecimal invoiceAmount) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        
        return routeInvoiceMapper.batchUpdateInvoiceAmount(ids, invoiceAmount) > 0;
    }

    @Override
    public Boolean batchUpdateRouteInvoiceStatus(RouteInvoiceBatchUpdateDTO batchUpdateDTO) {
        if (CollectionUtils.isEmpty(batchUpdateDTO.getIds())) {
            return false;
        }
        
        return routeInvoiceMapper.batchUpdateRouteInvoiceStatus(
                batchUpdateDTO.getIds(), 
                batchUpdateDTO.getStatus()
        ) > 0;
    }

    @Override
    public Map<String, Object> getRouteInvoiceStatistics(RouteInvoiceStatisticsDTO statisticsDTO) {
        Map<String, Object> result = new HashMap<>();
        
        // 总发票数
        Long totalCount = routeInvoiceMapper.selectCount(null);
        result.put("totalCount", totalCount);
        
        // 已开具发票数
        Long issuedCount = routeInvoiceMapper.countByStatus("ISSUED");
        result.put("issuedCount", issuedCount);
        
        // 待开具发票数
        Long pendingCount = routeInvoiceMapper.countByStatus("PENDING");
        result.put("pendingCount", pendingCount);
        
        // 已作废发票数
        Long voidCount = routeInvoiceMapper.countByStatus("VOID");
        result.put("voidCount", voidCount);
        
        // 已红冲发票数
        Long redCount = routeInvoiceMapper.countByStatus("RED_RUSH");
        result.put("redCount", redCount);
        
        // 按发票类型统计
        Map<String, Long> invoiceTypeStats = new HashMap<>();
        invoiceTypeStats.put("ORDINARY", routeInvoiceMapper.countByInvoiceType("ORDINARY"));
        invoiceTypeStats.put("SPECIAL", routeInvoiceMapper.countByInvoiceType("SPECIAL"));
        invoiceTypeStats.put("ELECTRONIC", routeInvoiceMapper.countByInvoiceType("ELECTRONIC"));
        result.put("invoiceTypeStats", invoiceTypeStats);
        
        // 发票金额统计
        BigDecimal totalAmount = routeInvoiceMapper.sumInvoiceAmount();
        result.put("totalAmount", totalAmount != null ? totalAmount : BigDecimal.ZERO);
        
        // 税额统计
        BigDecimal totalTaxAmount = routeInvoiceMapper.sumTaxAmount();
        result.put("totalTaxAmount", totalTaxAmount != null ? totalTaxAmount : BigDecimal.ZERO);
        
        return result;
    }

    @Override
    public List<RouteInvoiceVO> getIssuedInvoices(Integer limit) {
        List<RouteInvoice> routeInvoices = routeInvoiceMapper.selectIssuedInvoices(limit);
        return routeInvoices.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<RouteInvoiceVO> getPendingInvoices(Integer limit) {
        List<RouteInvoice> routeInvoices = routeInvoiceMapper.selectPendingInvoices(limit);
        return routeInvoices.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<RouteInvoiceVO> getVoidInvoices(Integer limit) {
        List<RouteInvoice> routeInvoices = routeInvoiceMapper.selectVoidInvoices(limit);
        return routeInvoices.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<RouteInvoiceVO> getRedRushInvoices(Integer limit) {
        List<RouteInvoice> routeInvoices = routeInvoiceMapper.selectRedRushInvoices(limit);
        return routeInvoices.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<RouteInvoiceVO> getInvoicesByType(String invoiceType, String status, Integer limit) {
        List<RouteInvoice> routeInvoices = routeInvoiceMapper.selectInvoicesByType(invoiceType, status, limit);
        return routeInvoices.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<RouteInvoiceVO> getInvoicesByTimeRange(LocalDateTime startTime, LocalDateTime endTime, Integer limit) {
        List<RouteInvoice> routeInvoices = routeInvoiceMapper.selectInvoicesByTimeRange(startTime, endTime, limit);
        return routeInvoices.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<RouteInvoiceVO> getInvoicesByAmountRange(BigDecimal minAmount, BigDecimal maxAmount, Integer limit) {
        List<RouteInvoice> routeInvoices = routeInvoiceMapper.selectInvoicesByAmountRange(minAmount, maxAmount, limit);
        return routeInvoices.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<RouteInvoiceVO> getInvoicesByTaxRate(BigDecimal taxRate, String status, Integer limit) {
        List<RouteInvoice> routeInvoices = routeInvoiceMapper.selectInvoicesByTaxRate(taxRate, status, limit);
        return routeInvoices.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<RouteInvoiceVO> getInvoicesByRoute(Long routeId, String status, Integer limit) {
        List<RouteInvoice> routeInvoices = routeInvoiceMapper.selectInvoicesByRoute(routeId, status, limit);
        return routeInvoices.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<RouteInvoiceVO> getInvoicesByMerchant(Long merchantId, String status, Integer limit) {
        List<RouteInvoice> routeInvoices = routeInvoiceMapper.selectInvoicesByMerchant(merchantId, status, limit);
        return routeInvoices.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public Boolean existsById(Long id) {
        return routeInvoiceMapper.selectById(id) != null;
    }

    @Override
    public Boolean existsByInvoiceNo(String invoiceNo, Long excludeId) {
        return routeInvoiceMapper.existsByInvoiceNo(invoiceNo, excludeId) > 0;
    }

    @Override
    public Boolean issueInvoice(Long invoiceId, String issueNotes) {
        RouteInvoice routeInvoice = routeInvoiceMapper.selectById(invoiceId);
        if (routeInvoice == null) {
            throw new RuntimeException("路线发票不存在: " + invoiceId);
        }
        
        routeInvoice.setStatus("ISSUED");
        routeInvoice.setIssueTime(LocalDateTime.now());
        routeInvoice.setUpdateTime(LocalDateTime.now());
        
        return routeInvoiceMapper.updateById(routeInvoice) > 0;
    }

    @Override
    public Boolean voidInvoice(Long invoiceId, String voidReason) {
        RouteInvoice routeInvoice = routeInvoiceMapper.selectById(invoiceId);
        if (routeInvoice == null) {
            throw new RuntimeException("路线发票不存在: " + invoiceId);
        }
        
        routeInvoice.setStatus("VOID");
        routeInvoice.setVoidTime(LocalDateTime.now());
        routeInvoice.setVoidReason(voidReason);
        routeInvoice.setUpdateTime(LocalDateTime.now());
        
        return routeInvoiceMapper.updateById(routeInvoice) > 0;
    }

    @Override
    public Boolean redRushInvoice(Long invoiceId, String redRushReason) {
        RouteInvoice routeInvoice = routeInvoiceMapper.selectById(invoiceId);
        if (routeInvoice == null) {
            throw new RuntimeException("路线发票不存在: " + invoiceId);
        }
        
        routeInvoice.setStatus("RED_RUSH");
        routeInvoice.setRedRushTime(LocalDateTime.now());
        routeInvoice.setRedRushReason(redRushReason);
        routeInvoice.setUpdateTime(LocalDateTime.now());
        
        return routeInvoiceMapper.updateById(routeInvoice) > 0;
    }

    @Override
    public Boolean auditInvoice(Long invoiceId, String auditResult, String auditNotes) {
        RouteInvoice routeInvoice = routeInvoiceMapper.selectById(invoiceId);
        if (routeInvoice == null) {
            throw new RuntimeException("路线发票不存在: " + invoiceId);
        }
        
        // 根据审核结果更新发票状态
        switch (auditResult) {
            case "APPROVED":
                routeInvoice.setStatus("APPROVED");
                break;
            case "REJECTED":
                routeInvoice.setStatus("REJECTED");
                break;
            case "PENDING":
                routeInvoice.setStatus("PENDING");
                break;
        }
        
        routeInvoice.setAuditTime(LocalDateTime.now());
        routeInvoice.setAuditNotes(auditNotes);
        routeInvoice.setUpdateTime(LocalDateTime.now());
        
        return routeInvoiceMapper.updateById(routeInvoice) > 0;
    }

    @Override
    public Boolean authenticateInvoice(Long invoiceId, String authenticationResult) {
        RouteInvoice routeInvoice = routeInvoiceMapper.selectById(invoiceId);
        if (routeInvoice == null) {
            throw new RuntimeException("路线发票不存在: " + invoiceId);
        }
        
        routeInvoice.setAuthenticationResult(authenticationResult);
        routeInvoice.setAuthenticationTime(LocalDateTime.now());
        routeInvoice.setUpdateTime(LocalDateTime.now());
        
        return routeInvoiceMapper.updateById(routeInvoice) > 0;
    }

    @Override
    public Boolean batchIssueInvoices(List<Long> invoiceIds, String issueNotes) {
        if (CollectionUtils.isEmpty(invoiceIds)) {
            return false;
        }
        
        for (Long invoiceId : invoiceIds) {
            issueInvoice(invoiceId, issueNotes);
        }
        
        return true;
    }

    @Override
    public Boolean batchVoidInvoices(List<Long> invoiceIds, String voidReason) {
        if (CollectionUtils.isEmpty(invoiceIds)) {
            return false;
        }
        
        for (Long invoiceId : invoiceIds) {
            voidInvoice(invoiceId, voidReason);
        }
        
        return true;
    }

    @Override
    public Boolean batchRedRushInvoices(List<Long> invoiceIds, String redRushReason) {
        if (CollectionUtils.isEmpty(invoiceIds)) {
            return false;
        }
        
        for (Long invoiceId : invoiceIds) {
            redRushInvoice(invoiceId, redRushReason);
        }
        
        return true;
    }

    @Override
    public Boolean batchAuditInvoices(List<Long> invoiceIds, String auditResult, String auditNotes) {
        if (CollectionUtils.isEmpty(invoiceIds)) {
            return false;
        }
        
        for (Long invoiceId : invoiceIds) {
            auditInvoice(invoiceId, auditResult, auditNotes);
        }
        
        return true;
    }

    @Override
    public Boolean batchAuthenticateInvoices(List<Long> invoiceIds, String authenticationResult) {
        if (CollectionUtils.isEmpty(invoiceIds)) {
            return false;
        }
        
        for (Long invoiceId : invoiceIds) {
            authenticateInvoice(invoiceId, authenticationResult);
        }
        
        return true;
    }

    @Override
    public Map<String, Object> getTaxAnalysis(LocalDateTime startTime, LocalDateTime endTime, String analysisType) {
        Map<String, Object> result = new HashMap<>();
        
        // 税务分析数据
        result.put("period", startTime + " - " + endTime);
        result.put("analysisType", analysisType);
        result.put("totalInvoices", 0);
        result.put("totalAmount", BigDecimal.ZERO);
        result.put("totalTaxAmount", BigDecimal.ZERO);
        result.put("averageTaxRate", BigDecimal.ZERO);
        result.put("taxRateDistribution", new ArrayList<>());
        result.put("monthlyTaxTrend", new ArrayList<>());
        
        return result;
    }

    @Override
    public Map<String, Object> getComplianceCheck(LocalDateTime startTime, LocalDateTime endTime, String checkType) {
        Map<String, Object> result = new HashMap<>();
        
        // 合规性检查数据
        result.put("period", startTime + " - " + endTime);
        result.put("checkType", checkType);
        result.put("totalChecked", 0);
        result.put("compliantCount", 0);
        result.put("nonCompliantCount", 0);
        result.put("complianceRate", 0.0);
        result.put("issues", new ArrayList<>());
        result.put("recommendations", new ArrayList<>());
        
        return result;
    }

    @Override
    public BigDecimal calculateTotalInvoiceAmount(LocalDateTime startTime, LocalDateTime endTime) {
        return routeInvoiceMapper.calculateTotalInvoiceAmount(startTime, endTime);
    }

    @Override
    public BigDecimal calculateTotalTaxAmount(LocalDateTime startTime, LocalDateTime endTime) {
        return routeInvoiceMapper.calculateTotalTaxAmount(startTime, endTime);
    }

    @Override
    public Integer calculateInvoiceCount(LocalDateTime startTime, LocalDateTime endTime, String status) {
        return routeInvoiceMapper.calculateInvoiceCount(startTime, endTime, status);
    }

    @Override
    public Double calculateAverageTaxRate(LocalDateTime startTime, LocalDateTime endTime) {
        return routeInvoiceMapper.calculateAverageTaxRate(startTime, endTime);
    }

    @Override
    public List<RouteInvoiceVO> searchInvoices(String keyword, String searchType, Integer limit) {
        List<RouteInvoice> routeInvoices = routeInvoiceMapper.searchInvoices(keyword, searchType, limit);
        return routeInvoices.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<RouteInvoiceVO> exportInvoices(RouteInvoiceQueryDTO queryDTO) {
        List<RouteInvoice> routeInvoices = routeInvoiceMapper.selectInvoiceList(queryDTO);
        return routeInvoices.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public Boolean importInvoices(List<RouteInvoiceDTO> invoices) {
        if (CollectionUtils.isEmpty(invoices)) {
            return false;
        }
        
        for (RouteInvoiceDTO invoiceDTO : invoices) {
            try {
                createRouteInvoice(invoiceDTO);
            } catch (Exception e) {
                // 记录导入失败的记录
                System.err.println("导入发票失败: " + invoiceDTO.getInvoiceNo() + ", 原因: " + e.getMessage());
            }
        }
        
        return true;
    }

    @Override
    public Boolean syncInvoiceData(Long invoiceId, String syncType) {
        // 发票数据同步逻辑
        RouteInvoice routeInvoice = routeInvoiceMapper.selectById(invoiceId);
        if (routeInvoice == null) {
            return false;
        }
        
        // 根据同步类型执行不同的同步逻辑
        switch (syncType) {
            case "TAX_SYSTEM":
                // 同步到税务系统
                break;
            case "FINANCIAL_SYSTEM":
                // 同步到财务系统
                break;
            case "ERP_SYSTEM":
                // 同步到ERP系统
                break;
            default:
                // 全量同步
                break;
        }
        
        return true;
    }

    @Override
    public Boolean batchSyncInvoiceData(List<Long> invoiceIds, String syncType) {
        if (CollectionUtils.isEmpty(invoiceIds)) {
            return false;
        }
        
        for (Long invoiceId : invoiceIds) {
            syncInvoiceData(invoiceId, syncType);
        }
        
        return true;
    }

    @Override
    public Boolean validateInvoice(Long invoiceId, String validationType) {
        // 发票验证逻辑
        RouteInvoice routeInvoice = routeInvoiceMapper.selectById(invoiceId);
        if (routeInvoice == null) {
            return false;
        }
        
        // 根据验证类型执行不同的验证逻辑
        switch (validationType) {
            case "FORMAT":
                // 格式验证
                break;
            case "TAX_RATE":
                // 税率验证
                break;
            case "AMOUNT":
                // 金额验证
                break;
            default:
                // 全面验证
                break;
        }
        
        return true;
    }

    @Override
    public Boolean batchValidateInvoices(List<Long> invoiceIds, String validationType) {
        if (CollectionUtils.isEmpty(invoiceIds)) {
            return false;
        }
        
        for (Long invoiceId : invoiceIds) {
            if (!validateInvoice(invoiceId, validationType)) {
                return false;
            }
        }
        
        return true;
    }

    @Override
    public Map<String, Object> getInvoiceAnalytics(LocalDateTime startTime, LocalDateTime endTime, String analyticsType) {
        Map<String, Object> result = new HashMap<>();
        
        // 获取发票分析数据
        result.put("period", startTime + " - " + endTime);
        result.put("analyticsType", analyticsType);
        result.put("totalInvoices", 0);
        result.put("issuedInvoices", 0);
        result.put("voidInvoices", 0);
        result.put("totalAmount", BigDecimal.ZERO);
        result.put("averageAmount", BigDecimal.ZERO);
        result.put("topRoutes", new ArrayList<>());
        result.put("topMerchants", new ArrayList<>());
        
        return result;
    }

    @Override
    public List<Map<String, Object>> getInvoiceTrends(LocalDateTime startTime, LocalDateTime endTime, String trendType) {
        // 获取发票趋势数据
        return routeInvoiceMapper.selectInvoiceTrends(startTime, endTime, trendType);
    }

    @Override
    public Boolean generateInvoiceReport(LocalDateTime startTime, LocalDateTime endTime, String reportType) {
        // 生成发票报告逻辑
        List<RouteInvoice> invoices = routeInvoiceMapper.selectInvoicesByTimeRange(startTime, endTime, null);
        
        // 根据报告类型生成不同的报告
        switch (reportType) {
            case "SUMMARY":
                // 生成汇总报告
                break;
            case "DETAIL":
                // 生成详细报告
                break;
            case "TAX":
                // 生成税务报告
                break;
            default:
                // 生成标准报告
                break;
        }
        
        return true;
    }

    @Override
    public Boolean batchGenerateInvoiceReports(List<String> reportTypes, LocalDateTime startTime, LocalDateTime endTime) {
        if (CollectionUtils.isEmpty(reportTypes)) {
            return false;
        }
        
        for (String reportType : reportTypes) {
            generateInvoiceReport(startTime, endTime, reportType);
        }
        
        return true;
    }

    @Override
    public Boolean archiveInvoice(Long invoiceId, String archiveReason) {
        // 发票归档逻辑
        RouteInvoice routeInvoice = routeInvoiceMapper.selectById(invoiceId);
        if (routeInvoice == null) {
            return false;
        }
        
        routeInvoice.setStatus("ARCHIVED");
        routeInvoice.setArchiveTime(LocalDateTime.now());
        routeInvoice.setArchiveReason(archiveReason);
        routeInvoice.setUpdateTime(LocalDateTime.now());
        
        return routeInvoiceMapper.updateById(routeInvoice) > 0;
    }

    @Override
    public Boolean batchArchiveInvoices(List<Long> invoiceIds, String archiveReason) {
        if (CollectionUtils.isEmpty(invoiceIds)) {
            return false;
        }
        
        for (Long invoiceId : invoiceIds) {
            archiveInvoice(invoiceId, archiveReason);
        }
        
        return true;
    }

    /**
     * 将RouteInvoice实体转换为RouteInvoiceVO
     */
    private RouteInvoiceVO convertToVO(RouteInvoice routeInvoice) {
        if (routeInvoice == null) {
            return null;
        }
        
        RouteInvoiceVO vo = new RouteInvoiceVO();
        BeanUtils.copyProperties(routeInvoice, vo);
        return vo;
    }

    /**
     * 将RouteInvoiceDTO转换为RouteInvoice实体
     */
    private RouteInvoice convertToEntity(RouteInvoiceDTO dto) {
        if (dto == null) {
            return null;
        }
        
        RouteInvoice entity = new RouteInvoice();
        BeanUtils.copyProperties(dto, entity);
        return entity;
    }
}